home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 2.iso / dist / fw_glimpse.idb / usr / freeware / src / glimpse-3.0 / index / dir.c.z / dir.c
C/C++ Source or Header  |  1997-09-09  |  15KB  |  485 lines

  1. /* Copyright (c) 1994 Sun Wu, Udi Manber, Burra Gopal.  All Rights Reserved. */
  2. /* ./glimpse/index/dir.c */
  3.  
  4. /* The function of the program is to traverse the
  5.    direcctory tree and print the size of the files in the tree.
  6.    This program is derived from the C-programming language book
  7.    It opens a directory file using opendir system call, and use readdir()
  8.    to read each entry of the directory.
  9. */
  10.  
  11. #include "autoconf.h"    /* ../libtemplate/include */
  12. #include <stdio.h>
  13. #include <sys/types.h>
  14.  
  15. #if HAVE_DIRENT_H
  16. # include <dirent.h>
  17. # define NAMLEN(dirent) strlen((dirent)->d_name)
  18. #else
  19. # define dirent direct
  20. # define NAMLEN(dirent) (dirent)->d_namlen
  21. # if HAVE_SYS_NDIR_H
  22. #  include <sys/ndir.h>
  23. # endif
  24. # if HAVE_SYS_DIR_H
  25. #  include <sys/dir.h>
  26. # endif
  27. # if HAVE_NDIR_H
  28. #  include <ndir.h>
  29. # endif
  30. #endif
  31.  
  32. #include <sys/stat.h>
  33. #include <fcntl.h>
  34. #define BUFSIZE 256
  35. #define DIRSIZE 14
  36. #include "glimpse.h"
  37. #undef MAX_LIST
  38. #define MAX_LIST 100000
  39.  
  40. #if    SFS_COMPAT
  41. #define FS_TYPEMASK    0x700000
  42. #define FS_LINK        0x300000
  43. #endif
  44.  
  45. #if    BG_DEBUG
  46. extern FILE *LOGFILE;
  47. #endif    /*BG_DEBUG*/
  48. extern FILE *MESSAGEFILE;
  49. int ndx = 0;                    /* file index */
  50. extern char **name_list[MAXNUM_INDIRECT];  /* store the file names */
  51. extern int  *size_list[MAXNUM_INDIRECT];   /* store the sizes of the files */
  52. extern unsigned int *disable_list;   /* store whether to DISABLE indexing or not: only with FastIndex or AddToIndex */
  53. extern int  file_num;
  54. extern int  file_id;    /* borrowed from filetype.c */
  55. extern char INDEX_DIR[MAX_LINE_LEN];
  56. extern int AddToIndex;
  57. extern int DeleteFromIndex;
  58. extern int FastIndex;
  59. extern int OneFilePerBlock;
  60. extern int IncludeHigherPriority;
  61. extern int BuildDictionaryExisting;
  62. extern int IndexEverything;
  63. extern int printed_warning;
  64. extern int p_table[];
  65. extern FILE *STATFILE;
  66.  
  67. extern int IndexableFile;
  68. extern int files_per_partition;
  69. extern int new_partition;
  70. extern int files_in_partition;
  71. extern struct stat istbuf;    /* imported from glimpse.c */
  72. extern int memory_usage;
  73. extern int mask_int[];
  74.  
  75. extern char exin_argv[8];
  76. extern int exin_argc;
  77. extern char current_dir_buf[2*MAX_LINE_LEN + 4];    /* must have space to store pattern after directory name */
  78. extern unsigned char dummypat[MAX_PAT];
  79. extern int dummylen;
  80. extern FILE *dummyout;
  81.  
  82. extern struct stat excstbuf;
  83. extern struct stat incstbuf;
  84.  
  85. extern int num_filter;
  86. extern int filter_len[MAX_FILTER];
  87. extern CHAR *filter[MAX_FILTER];
  88. extern CHAR *filter_command[MAX_FILTER];
  89.  
  90. /*
  91.  * Exclude/Include priorities with exclude > include (IncludeHigherPriority = OFF = default):
  92.  * 1. Command line arguments (inclusion --> exclude list is never applied)
  93.  * 2. Exclude list (exclusion)
  94.  * 3. Include list (inclusion)
  95.  * 5. Symbolic links (exclusion --> applying exclude list is unnecessary)
  96.  * 4. filetype (exclusion)
  97.  * 
  98.  * Exclude/Include priorities with include > exclude (IncludeHigherPriority = ON = -i):
  99.  * 1. Command line arguments (inclusion --> exclude list is never applied)
  100.  * 2. Include list (inclusion)
  101.  * 3. Symbolic links (exclusion --> applying exclude list is unnecessary)
  102.  * 3. Exclude list (exclusion)
  103.  * 4. filetype (exclusion)
  104.  */
  105.  
  106. char outname[MAX_LINE_LEN];
  107. char inname[MAX_LINE_LEN];
  108.  
  109. fsize(name, pat, pat_len, num_pat, inc, inc_len, num_inc, toplevel)
  110. char *name;
  111. char **pat;
  112. int *pat_len;
  113. int num_pat;
  114. char **inc;
  115. int *inc_len;
  116. int num_inc;
  117. int toplevel;
  118. {
  119.     struct stat stbuf;
  120.     int i;
  121.     int fileindex = -1;
  122.     int force_include = 0;
  123.     int len_current_dir_buf = strlen(current_dir_buf) + 1;    /* includes the '\0' which is going to be replaced by '\n' below */
  124.     int name_len;
  125.     char *t1;
  126.  
  127.     if ((name == NULL) || (*name == '\0')) return 0;
  128.     name_len = strlen(name);    /* name[name_len] is '\0' */
  129.  
  130. #ifdef    SW_DEBUG
  131.     printf("num_pat= %d num_inc= %d\n", num_pat, num_inc);
  132.     printf("name= %s\n", name);
  133. #endif
  134.  
  135.     /*
  136.      * Find out what to exclude, what to include and skip
  137.      * over symbolic links that don't HAVE to be included.
  138.      * Some Extra get_filename_index calls are done but
  139.      * that won't cost you anything (just #ing twice).
  140.      */
  141.  
  142.     /* Check if cache set in glimpse.c is correct */
  143.     if (!IndexableFile && !DeleteFromIndex && FastIndex && ((fileindex = get_filename_index(name, name_list, file_num)) != -1) && (disable_list[block2index(fileindex)] & mask_int[fileindex % (8*sizeof(int))])) {
  144.         if (num_pat <= 0) {
  145.         if (num_inc <= 0) return 0;
  146.         else if (incstbuf.st_ctime <= istbuf.st_ctime) return 0;
  147.         }
  148.         else {
  149.         if (num_inc <= 0) {
  150.             if (excstbuf.st_ctime <= istbuf.st_ctime) return 0;
  151.         }
  152.         else if ((excstbuf.st_ctime <= istbuf.st_ctime) && (incstbuf.st_ctime <= istbuf.st_ctime)) return 0;
  153.         }
  154.     }
  155.  
  156. #define PROCESS_EXIT \
  157. {\
  158.     if (AddToIndex || FastIndex || DeleteFromIndex) {\
  159.         if ((fileindex = get_filename_index(name, name_list, file_num)) != -1) \
  160.             remove_filename(fileindex, new_partition);\
  161.     }\
  162. }
  163.  
  164. #define PROCESS_EXCLUDE \
  165. {\
  166.     if (!toplevel) for(i=0; i<num_pat; i++) {    /* bg: 15/mar/94 */\
  167.         if (pat_len[i] > 0) {\
  168.             name[name_len] = '\0';\
  169.             if (strstr(name, pat[i]) != NULL) {\
  170.                 PROCESS_EXIT;\
  171.                 return 0;\
  172.             }\
  173.         }\
  174.         else {    /* must call memagrep */\
  175.             int    ret;\
  176.             name[name_len] = '\n';    /* memagrep wants names to end with '\n': '\0' is not necessary */\
  177.             /* printf("i=%d patlen=%d pat=%s inlen=%d input=%s\n", i, -pat_len[i], pat[i], len_current_dir_buf, current_dir_buf); */\
  178.             if (((pat_len[i] == -2) && (pat[i][0] == '.') && (pat[i][1] == '*')) ||\
  179.                 ((ret = memagrep_search(-pat_len[i], pat[i], len_current_dir_buf, current_dir_buf, 0, dummyout)) > 0))\
  180.             {\
  181.                 /* printf("excluding with %d %s\n", ret, name); */\
  182.                 name[name_len] = '\0';    /* restore */\
  183.                 PROCESS_EXIT;\
  184.                   return 0; \
  185.             }\
  186.             /* else printf("ret=%d\n");*/\
  187.         }\
  188.     }\
  189.     name[name_len] = '\0';\
  190. }
  191.  
  192. #define PROCESS_INCLUDE \
  193. {\
  194.      /*\
  195.      * When include has higher priority, we want to include directories\
  196.      * by default and match the include patterns only against filenames.\
  197.      * Based on bug reports for glimpse-2.1. bg: 2/mar/95.\
  198.       */\
  199.      if (IncludeHigherPriority && ((stbuf.st_mode & S_IFMT) == S_IFDIR)) force_include = 1;\
  200.      else for (i=0; i<num_inc; i++) {    /* bg: 15/mar/94 */\
  201.         if (inc_len[i] > 0) {\
  202.             name[name_len] = '\0';\
  203.             if (strstr(name, inc[i]) != NULL) {\
  204.                 force_include = 1;\
  205.                 break;\
  206.             }\
  207.         }\
  208.         else {    /* must call memagrep */\
  209.             name[name_len] = '\n';    /* memagrep wants names to end with '\n': '\0' is not necessary */\
  210.             /* printf("pat=%s input=%s\n", pat[i], current_dir_buf); */\
  211.             if (((inc_len[i] == -2) && (inc[i][0] == '.') && (inc[i][1] == '*')) ||\
  212.                 (memagrep_search(-inc_len[i], inc[i], len_current_dir_buf, current_dir_buf, 0, dummyout) > 0))\
  213.             {\
  214.                 force_include = 1;\
  215.                 break;\
  216.             }\
  217.         }\
  218.     }\
  219.     if (!force_include) for (i=0; i<num_filter; i++) {    /* bg: 16/sep/94 */\
  220.         if (filter_len[i] > 0) {\
  221.             name[name_len] = '\0';\
  222.             if (strstr(name, filter[i]) != NULL) {\
  223.                 force_include = 1;\
  224.                 break;\
  225.             }\
  226.         }\
  227.         else {    /* must call memagrep */\
  228.             name[name_len] = '\n';    /* memagrep wants names to end with '\n': '\0' is not necessary */\
  229.             /* printf("pat=%s input=%s\n", pat[i], current_dir_buf); */\
  230.             if (((filter_len[i] == -1) && (filter[i][0] == '.') && (filter[i][1] == '*')) ||\
  231.                 (memagrep_search(-filter_len[i], filter[i], len_current_dir_buf, current_dir_buf, 0, dummyout) > 0))\
  232.             {\
  233.                 force_include = 1;\
  234.                 break;\
  235.             }\
  236.         }\
  237.     }\
  238.     name[name_len] = '\0';    /* restore */\
  239.     if (toplevel) force_include = 1;\
  240. }
  241.  
  242.         if(lstat(name, &stbuf) == -1) {
  243.         if (IndexableFile) return 0;
  244.         /* Can happen for command line arguments, not stuff obtained from fsize_directory() */
  245. #if    BG_DEBUG
  246.         fprintf(LOGFILE, "cannot find %s -- not indexing\n", name);
  247. #endif    /*BG_DEBUG*/
  248.         PROCESS_EXIT;
  249.         return 0;
  250.     }
  251.     /* Else lstat has all the requisite information */
  252.  
  253. #if    SFS_COMPAT
  254.     if ((stbuf.st_spare1 & FS_TYPEMASK) == FS_LINK) return 0;
  255. #endif
  256.     if ((stbuf.st_mode & S_IFMT) == S_IFLNK)  {
  257.         /* if (IndexableFile) return 0; ---> not correct! must process include/exclude with -I too */
  258.         PROCESS_INCLUDE;
  259.         if (!force_include) {
  260. #if    BG_DEBUG
  261.             fprintf(LOGFILE, "%s is a symbolic link -- not indexing\n", name);
  262. #endif    /*BG_DEBUG*/
  263.             PROCESS_EXIT;
  264.             return 0;
  265.         }
  266.         if (-1 == stat(name, &stbuf)) {
  267. #if    BG_DEBUG
  268.             fprintf(LOGFILE, "cannot find target of symbolic link %s -- not indexing\n", name);
  269. #endif    /*BG_DEBUG*/
  270.             PROCESS_EXIT;
  271.             return 0;
  272.         }
  273.     }
  274.     else /* if (!IndexableFile) ---> not correct! must process include/exclude with -I too */ {
  275.         /* Put exclude include processing here... stat all the time: that is faster than former! */
  276.         if (FastIndex && ((fileindex = get_filename_index(name, name_list, file_num)) != -1)) {
  277.             /* Don't process exclude/include if the file `name' is older then the index AND the exclude/include file is older then the index */
  278.             if (IncludeHigherPriority) {
  279.                 if (!((stbuf.st_ctime <= istbuf.st_ctime) && (incstbuf.st_ctime <= istbuf.st_ctime)))
  280.                     PROCESS_INCLUDE;
  281.                 if (!force_include && !((stbuf.st_ctime <= istbuf.st_ctime) && (excstbuf.st_ctime <= istbuf.st_ctime)))
  282.                     PROCESS_EXCLUDE;
  283.             }
  284.             else {
  285.                 if (!((stbuf.st_ctime <= istbuf.st_ctime) && (excstbuf.st_ctime <= istbuf.st_ctime)))
  286.                     PROCESS_EXCLUDE;
  287.                 if (!((stbuf.st_ctime <= istbuf.st_ctime) && (incstbuf.st_ctime <= istbuf.st_ctime)))
  288.                     PROCESS_INCLUDE;
  289.             }
  290.         }
  291.         else {    /* Either AddToIndex or fresh indexing or previously excluded file: process exclude and include */
  292.             if (IncludeHigherPriority) {
  293.                 PROCESS_INCLUDE;
  294.                 if (!force_include)
  295.                     PROCESS_EXCLUDE;
  296.             }
  297.             else {
  298.                 PROCESS_EXCLUDE;
  299.                 PROCESS_INCLUDE;
  300.             }
  301.         }
  302.     }
  303.  
  304.     /* Here, the file exists and has not been excluded -- possibly has been included */
  305. index_everything:
  306.     if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
  307.         if (-1 == fsize_directory(name, pat, pat_len, num_pat, inc, inc_len, num_inc)) return -1;
  308.     }
  309.         else if ((stbuf.st_mode & S_IFMT) == S_IFREG) {    /* regular file */
  310.         if (IndexableFile) {
  311.         if (!filetype(name, IndexEverything?2:1)) printf("%s\n", name);
  312.         return 0;
  313.         }
  314.         if (DeleteFromIndex) {
  315.         if ((fileindex = get_filename_index(name, name_list, file_num)) != -1) {
  316.             remove_filename(fileindex, new_partition);
  317.         }
  318.         /* else doesn't exist in index, so doesn't matter */
  319.         return 0;
  320.         }
  321.         file_id ++;
  322.         if (BuildDictionaryExisting) {
  323.         /* Don't even store the names of the files that are not uncompressible */
  324.         if (file_num >= MaxNum24bPartition) {
  325.             fprintf(stderr, "Too many files in index: indexing the first %d only.\n", MaxNum24bPartition);
  326.             return -1;
  327.         }
  328.             if (tuncompress_file(name, outname, TC_EASYSEARCH | TC_OVERWRITE | TC_NOPROMPT) <= 0) return 0;
  329.         file_num++;
  330.         t1 = (char *) my_malloc(strlen(outname) + 2);
  331.         strcpy(t1, outname);
  332.         /* name_list[ndx] = t1; */
  333.         LIST_ADD(name_list, ndx, t1, char*);
  334.         /* size_list[ndx] = stbuf.st_size;*/
  335.         LIST_ADD(size_list, ndx, stbuf.st_size, int);
  336.         ndx ++;
  337.         return 0;
  338.         }
  339.  
  340. #ifdef SW_DEBUG
  341.         printf("%s: ", name);
  342. #endif
  343.  
  344.         if (AddToIndex || FastIndex) {
  345.         if ((fileindex = get_filename_index(name, name_list, file_num)) != -1) {
  346.             LIST_ADD(size_list, fileindex, stbuf.st_size, int);
  347.             if (FastIndex && (stbuf.st_ctime <= istbuf.st_ctime))
  348.             disable_list[block2index(fileindex)] |= mask_int[fileindex % (8*sizeof(int))];
  349.             else { /* AddToIndex or file was modified (=> its type might have changed!) */
  350.             if (filetype(name, IndexEverything?2:1)) {
  351.                 if (!force_include) {
  352.                 remove_filename(fileindex, new_partition);
  353.                 return 0;
  354.                 }
  355.                 else {
  356. #if    BG_DEBUG
  357.                 fprintf(LOGFILE, "overriding and indexing: %s\n", name);
  358. #endif    /*BG_DEBUG*/
  359.                 }
  360.             }
  361.             disable_list[block2index(fileindex)] &= ~(mask_int[fileindex % (8*sizeof(int))]);
  362.             }
  363.         }
  364.         else {    /* new file not in filenames so no point in checking */
  365.             if(filetype(name, IndexEverything?2:1)) {
  366.             if (!force_include) return 0;
  367.             else {
  368. #if    BG_DEBUG
  369.                 fprintf(LOGFILE, "overriding and indexing: %s\n", name);
  370. #endif    /*BG_DEBUG*/
  371.             }
  372.             }
  373.  
  374.             if (file_num >= MaxNum24bPartition) {
  375.             fprintf(stderr, "Too many files in index: indexing the first %d only.\n", MaxNum24bPartition);
  376.             return -1;
  377.             }
  378.             t1 = (char *)my_malloc(strlen(name) + 2);
  379.             strcpy(t1, name);
  380.             /* name_list[file_num] = t1; */
  381.             LIST_ADD(name_list, file_num, t1, char*);
  382.             /* size_list[file_num] = stbuf.st_size; */
  383.             LIST_ADD(size_list, file_num, stbuf.st_size, int);
  384.             insert_filename(LIST_GET(name_list, file_num), file_num);
  385.             file_num ++;
  386.  
  387.             if (!OneFilePerBlock) {
  388.                 if (files_in_partition + 1 > files_per_partition) {
  389.                 if (new_partition + 1 > MaxNumPartition) {
  390.                 if (!printed_warning) {
  391.                     printed_warning = 1;
  392.                     if (AddToIndex) {
  393.                     fprintf(MESSAGEFILE, "Warning: partition-table overflow! Fresh indexing recommended.n");
  394.                     }
  395.                     else {
  396.                     fprintf(MESSAGEFILE, "Warning: partition-table overflow! Commencing fresh indexing...\n");
  397.                     return -1;
  398.                     }
  399.                 }
  400.                 }
  401.                 else new_partition++;
  402.                 files_in_partition = 0;
  403.                 /* so that we don't get into this if-branch until another files_per_partition new files are seen */
  404.             }
  405.  
  406.             p_table[new_partition] = file_num;
  407.             files_in_partition ++;
  408.             }
  409.         }
  410.         }
  411.         else { /* Fresh indexing: very simple -- add everything */
  412.         if(filetype(name, IndexEverything?2:1)) {
  413.             if (!force_include) return 0;
  414.             else {
  415. #if    BG_DEBUG
  416.             fprintf(LOGFILE, "overriding and indexing: %s\n", name);
  417. #endif    /*BG_DEBUG*/
  418.             }
  419.         }
  420.         if (file_num >= MaxNum24bPartition) {
  421.             fprintf(stderr, "Too many files in index: indexing the first %d only.\n", MaxNum24bPartition);
  422.             return -1;
  423.         }
  424.         file_num++;
  425.         t1 = (char *) my_malloc(strlen(name) + 2);
  426.         strcpy(t1, name);
  427.         /* name_list[ndx] = t1; */
  428.         LIST_ADD(name_list, ndx, t1, char*);
  429.         /* size_list[ndx] = stbuf.st_size; */
  430.         LIST_ADD(size_list, ndx, stbuf.st_size, int);
  431.         ndx++;
  432.         }
  433.         }
  434.     return 0;
  435. }
  436.  
  437. /* uses the space in the same "name" to get names of files in that directory and calls fsize */
  438. /* pat, pat_len, num_pat, inc, inc_len, num_inc are just used for recursive calls to fsize */
  439. fsize_directory(name, pat, pat_len, num_pat, inc, inc_len, num_inc)
  440. char *name;
  441. char **pat;
  442. int *pat_len;
  443. int  num_pat;
  444. char **inc;
  445. int *inc_len;
  446. int  num_inc;
  447. {
  448.     struct dirent *dp;
  449.     char *nbp, *nep;
  450.     int i;
  451.     DIR *dirp;
  452.     /*
  453.     printf("in fsize_directory, name= %s\n",name);
  454.     */
  455.     if ((name == NULL) || (*name == '\0')) return 0;
  456.     nbp = name + strlen(name);
  457.     if( nbp+DIRSIZE+2 >= name+BUFSIZE ) /* name too long */
  458.     {       fprintf(stderr, "name too long: %s\n", name);
  459.         return 0;
  460.     }
  461.         if((dirp = opendir(name)) == NULL) {
  462.         fprintf(stderr, "permission denied or non-existent directory: %s\n", name);
  463.         return 0;
  464.     }
  465.     *nbp++ = '/';
  466.         for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  467.             if (dp->d_name[0] == '\0' || strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue;
  468.         for(i=0, nep=nbp; (dp->d_name[i] != '\0') && (nep < name+BUFSIZ-1); i++)
  469.             *nep++ = dp->d_name[i];
  470.         if (dp->d_name[i] != '\0') {
  471.             *nep = '\0';
  472.             fprintf(stderr, "name too long: %s\n", name);
  473.             continue;
  474.         }
  475.         *nep = '\0';
  476.         /*
  477.         printf("name= %s\n", name);
  478.         */
  479.         if (-1 == fsize(name, pat, pat_len, num_pat, inc, inc_len, num_inc, 0)) return -1;
  480.     }
  481.         closedir (dirp);
  482.     *--nbp = '\0'; /* restore name */
  483.     return 0;
  484. }
  485.